package com.jzo2o.orders.manager.job;

import com.jzo2o.api.market.dto.request.CouponUseBackReqDTO;
import com.jzo2o.api.market.dto.response.CouponDto;
import com.jzo2o.api.trade.RefundRecordApi;
import com.jzo2o.api.trade.dto.response.ExecutionResultResDTO;
import com.jzo2o.api.trade.enums.RefundStatusEnum;
import com.jzo2o.common.expcetions.BadRequestException;
import com.jzo2o.common.expcetions.DBException;
import com.jzo2o.common.model.CurrentUserInfo;
import com.jzo2o.common.utils.CollUtils;
import com.jzo2o.common.utils.ObjectUtils;
import com.jzo2o.orders.base.config.OrderStateMachine;
import com.jzo2o.orders.base.enums.OrderStatusChangeEventEnum;
import com.jzo2o.orders.base.model.domain.Orders;
import com.jzo2o.orders.base.model.domain.OrdersCanceled;
import com.jzo2o.orders.base.model.domain.OrdersRefund;
import com.jzo2o.orders.base.model.dto.OrderSnapshotDTO;
import com.jzo2o.orders.manager.client.MarkerClient;
import com.jzo2o.orders.manager.service.IOrdersCanceledService;
import com.jzo2o.orders.manager.service.IOrdersManagerService;
import com.jzo2o.orders.manager.service.IOrdersRefundService;
import com.xxl.job.core.handler.annotation.XxlJob;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * TODO
 *
 * @Author lyh
 * @Date 2024/12/13 14:08
 */
@Component
@Slf4j
public class OrderJob {
    @Autowired
    private IOrdersRefundService refundService;
    @Autowired
    private ApplicationContext applicationContext;

    @Autowired
    private OrderStateMachine orderStateMachine;
    @XxlJob("handleRefundOrders")
    public void batchOrderRefund(){
        List<OrdersRefund> list = refundService.lambdaQuery().last("limit 100").list();
        if(CollUtils.isEmpty(list)){
            return;
        }
        OrderJob owner = applicationContext.getBean(OrderJob.class);
        for (OrdersRefund refund : list) {
            owner.orderRefund(refund);
        }
    }
    @Autowired
    private RefundRecordApi refundRecordApi;
    @Autowired
    private IOrdersManagerService ordersManagerService;
    @Transactional(rollbackFor = Exception.class)
    public  void orderRefund(OrdersRefund refund) {
        ExecutionResultResDTO executionResultResDTO=null;
        try {
            executionResultResDTO = refundRecordApi.refundTrading(refund.getTradingOrderNo(), refund.getRealPayAmount());
            //如果状态为退款中，则等待三秒，再调一次
            if(ObjectUtils.equals(executionResultResDTO.getRefundStatus(), RefundStatusEnum.SENDING.getCode())){
                TimeUnit.SECONDS.sleep(3);
                executionResultResDTO=refundRecordApi.refundTrading(refund.getTradingOrderNo(), refund.getRealPayAmount());
            }
        } catch (Exception e) {
            log.error("退款接口调用失败，退款信息为:{},失败原因为:{}",refund,e);
            throw new BadRequestException(e);
        }
        //判断executionResultResDTO是否为空
        if(ObjectUtils.isNull(executionResultResDTO)){
            log.error("退款接口调用失败，退款信息为:"+refund);
            throw new BadRequestException("退款接口调用失败，退款信息为:"+refund);
        }
        //判断退款状态是否为2
        if(!ObjectUtils.equals(executionResultResDTO.getRefundStatus(),RefundStatusEnum.SUCCESS.getCode())){
            log.error("退款接口调用失败，退款信息为:"+refund);
            throw new BadRequestException("退款接口调用失败，退款信息为:"+refund);
        }
        //修改订单信息 调用订单派单取消处理器
        OrderSnapshotDTO orderSnapshotDTO=new OrderSnapshotDTO();
        orderSnapshotDTO.setId(refund.getId());
        orderSnapshotDTO.setThirdRefundOrderId(executionResultResDTO.getRefundId());
        orderSnapshotDTO.setRefundNo(executionResultResDTO.getRefundNo());
        orderSnapshotDTO.setRefundStatus(executionResultResDTO.getRefundStatus());
        Orders orders = ordersManagerService.getById(refund.getId());
        orderStateMachine.changeStatus(orders.getUserId(), refund.getId().toString(), OrderStatusChangeEventEnum.CLOSE_DISPATCHING_ORDER,orderSnapshotDTO);
    boolean b = refundService.removeById(refund.getId());
    if(!b){
        throw new DBException("退款，删除退款记录失败");
    }
    log.info("退款成功，退款信息:{},退款状态为:{}",refund,executionResultResDTO.getRefundStatus());
    }
   @Autowired
   private IOrdersCanceledService ordersCanceledService;

    @Autowired
    private MarkerClient markerClient;
    @Async("taskExecutor")
    @GlobalTransactional
    public void cancelOrderByDispatching(Orders orders, String cancelReason, CurrentUserInfo userInfo) {
        //添加取消订单记录
        OrdersCanceled canceled = new OrdersCanceled();
        canceled.setId(orders.getId());
        canceled.setCancelReason(cancelReason);
        canceled.setCancellerId(userInfo.getId());
        canceled.setCancelerName(userInfo.getName());
        canceled.setCancellerType(userInfo.getUserType());
        canceled.setCancelTime(LocalDateTime.now());
        boolean save = ordersCanceledService.save(canceled);
        if(!save){
            throw new DBException("添加取消记录失败");
        }
        //修改订单状态
//        boolean update = ordersManagerService.lambdaUpdate().eq(Orders::getId,orders.getId())
//                .set(Orders::getOrdersStatus, OrderStatusEnum.CLOSED.getStatus())
//                .set(Orders::getRefundStatus, RefundStatusEnum.SENDING.getCode())
//                .update();
//        if(!update){
//            throw new DBException("订单修改失败");
//        }
        //添加退款记录
        OrdersRefund refund = new OrdersRefund();
        refund.setId(orders.getId());
        refund.setRealPayAmount(BigDecimal.valueOf(0.01));
        refund.setTradingOrderNo(orders.getTradingOrderNo());
        boolean save1 = refundService.save(refund);
        if(!save1){
            throw new DBException("添加退款记录失败");
        }
        //说明使用了优惠券
        if(ObjectUtils.isNotNull(orders.getDiscountAmount())&&orders.getDiscountAmount().compareTo(BigDecimal.ZERO)>0){
            CouponUseBackReqDTO dto = new CouponUseBackReqDTO();
            CouponDto coupon = markerClient.getCouponByOrdersId(orders.getId());
            dto.setId(coupon.getId());
            dto.setOrdersId(orders.getId());
            dto.setUserId(userInfo.getId());
            markerClient.useBack(dto);
        }
        // 申请退款
        OrderJob owner = applicationContext.getBean(OrderJob.class);
        owner.orderRefund(refund);

    }
}
